package com.qltv.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import com.qltv.menu.Menu;
import com.qltv.pojo.AccessToken;
import com.qltv.pojo.WeixinUserInfo;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

/**
 * 
 * 类名：WeixinUtil
 * 描述：微信公众平台通用接口工具类
 * @author telnet
 * 创建时间：2018年1月12日
 */
public class WeixinUtil {
	private static final Logger logger = Logger.getLogger(WeixinUtil.class);
	//获取access_token的接口地址（GET），限200（次/天）
	//public static final String access_token_url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx314b84ea36660a09&secret=98ee5ea48ec9f8763792ab1c0bbe5576";
	public static final String access_token_url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	//菜单创建（POST）， 限100（次/天）
	public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
	/**
	 * 创建菜单
	 * @param menu 菜单实例
	 * @param accessToken 有效的access_token
	 * @return 0表示成功，其他值表示失败
	 */
	public static int createMenu(Menu menu,String accessToken){
		int result = 0;
		//拼装创建菜单的url
		String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
		//将菜单对象转换成json字符串
		String jsonMenu = JSONObject.fromObject(menu).toString();
		//调用接口创建菜单
		JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
		if(null!=jsonObject){
			if(0!=jsonObject.getInt("errcode")){
				result = jsonObject.getInt("errcode");
				logger.error("创建菜单失败，errcode:{"+jsonObject.getInt("errcode")+"} errmsg:{"+jsonObject.getString("errmsg")+"}");
			}
		}
		
		
		logger.info(url);
		return result;
	}
	
	/**
	 * 获取access_token
	 * @param appid 凭证
	 * @param appsecret 密钥
	 * @return
	 */
	public static AccessToken getAccessToken(String appid,String appsecret){
		AccessToken accessToken = null;
		String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		if(null!=jsonObject){
			try {
				accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
			} catch (JSONException e) {
				accessToken = null;
				logger.error("获取token失败，errcode:{"+jsonObject.getInt("errcode")+"}errmsg:{"+jsonObject.getString("errmsg")+"}");
			}
		}
		return accessToken;
	}
	/**
	 * 发起HTTPS请求并获取结果
	 * @param requestUrl
	 * @param requestMethod
	 * @param outputStr
	 * @return
	 */
	public static JSONObject httpRequest(String requestUrl,String requestMethod,String outputStr){
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		
		
		try {
			TrustManager[] tm = {new MyX509TrustManager()};
			SSLContext sslContext;
			sslContext = SSLContext.getInstance("SSL","SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);
			
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			//设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);
			if("GET".equalsIgnoreCase(requestMethod)){
				httpUrlConn.connect();
			}
			//当有数据提交时
			if(null!=outputStr){
				OutputStream outputStream = httpUrlConn.getOutputStream();
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			//将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			while((str=bufferedReader.readLine())!=null){
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonObject = JSONObject.fromObject(buffer.toString());
		} catch (ConnectException ce) {
			logger.error("Weixin server connection timed out.");
		} catch(Exception e){
			logger.error("https request error : " + e);
		}
		return jsonObject;
	}
	
	
	public static WeixinUserInfo getUserInfo(String accessToken,String openId){
		WeixinUserInfo weixinUserInfo = null;
		String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
		requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
		//获取用户信息
		JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
		logger.info(jsonObject);
		if(null!=jsonObject){
			weixinUserInfo = new WeixinUserInfo();
			weixinUserInfo.setOpenId(jsonObject.getString("openid"));
			weixinUserInfo.setSubscribe(jsonObject.getInt("subscribe"));
			weixinUserInfo.setSubscribeTime(jsonObject.getString("subscribe_time"));
			weixinUserInfo.setNickname(jsonObject.getString("nickname"));
			weixinUserInfo.setSex(jsonObject.getInt("sex"));
			weixinUserInfo.setLanguage(jsonObject.getString("language"));
			weixinUserInfo.setCity(jsonObject.getString("city"));
			weixinUserInfo.setProvince(jsonObject.getString("province"));
			weixinUserInfo.setCountry(jsonObject.getString("country"));
			weixinUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
		}
		return weixinUserInfo;
		
	}
	
	public static Map<String, Object> getWxConfi(HttpServletRequest request){
		Map<String, Object> map = new HashMap<String, Object>();
		String appId = "wx314b84ea36660a09";
		String appsecret = "98ee5ea48ec9f8763792ab1c0bbe5576";
		
		String requestUrl = request.getRequestURL().toString();
		String access_token = "";
		String jsapi_ticket = "";
		String timestamp = Long.toString(System.currentTimeMillis()/1000);//必填，生成签名的时间戳
		String nonceStr = UUID.randomUUID().toString();//必填，生成签名的随机串
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId + "&secret=" + appsecret;
		JSONObject jsonObject = WeixinUtil.httpRequest(url, "GET", null);
		
		if(jsonObject !=null){
			//注意：access_token需要缓存
			access_token = jsonObject.getString("access_token");
			url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token + "&type=jsapi";
			jsonObject = WeixinUtil.httpRequest(url, "GET", null);
			if(jsonObject!=null){
				jsapi_ticket = jsonObject.getString("ticket");
			}
		}
		
		String signature = "";
		//所有参数名必须小写，而且必须有顺序
		String sign = "jsapi_ticket="+jsapi_ticket+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url"+requestUrl;
		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(sign.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		map.put("appId", appId);
		map.put("timestamp",timestamp);
		map.put("nonceStr", nonceStr);
		map.put("signature", signature);
		return map;
	}
	
	/**
	 * 字符串加密辅助方法
	 * @param hash
	 * @return
	 */
	public static String byteToHex(final byte[] hash){
		Formatter formatter = new Formatter();
		for (byte b : hash) {
			formatter.format("%02x", b);
		}
		String result = formatter.toString();
		formatter.close();
		return result;
	}
	

}
